﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using Common.Core;

namespace Web.Identity.Core
{
    public static class IdentityClaimExtension
    {
        public static void AddOrUpdateClaim(this ClaimsIdentity identity, Claim claim)
        {
            var oldClaim = identity.TryGetClaim(claim.Type);
            if (oldClaim != null) identity.TryRemoveClaim(oldClaim);
            identity.AddClaim(claim);
        }

        public static void AddOrUpdateClaim(this ClaimsIdentity identity, string type, string value)
        {
            if (type.IsNullOrBlank() || value.IsNullOrBlank())
                return;
            var claim = new Claim(type, value);
            var oldClaim = identity.TryGetClaim(type);
            if (oldClaim != null) identity.TryRemoveClaim(oldClaim);
            identity.AddClaim(claim);
        }

        public static void AddOrUpdateClaims(this ClaimsIdentity identity, IEnumerable<Claim> claims)
        {
            foreach (var claim in claims)
            {
                identity.AddOrUpdateClaim(claim);
            }
        }

        public static void AddOrUpdateClaims(this ClaimsIdentity identity, Dictionary<string, string> claims)
        {
            foreach (var claim in claims)
            {
                identity.AddOrUpdateClaim(claim.Key, claim.Value);
            }
        }

        public static void AddOrUpdateClaims(this ClaimsIdentity identity, object claims)
        {
            foreach (var claim in claims.ToDictionary())
            {
                identity.AddOrUpdateClaim(new Claim(claim.Key, claim.Value.IfNotNull(i => i.ToString())));
            }
        }

        public static IDictionary<string, object> ToDictionary(this object data)
        {
            var attr = BindingFlags.Public | BindingFlags.Instance;
            var dict = new Dictionary<string, object>();
            foreach (var property in data.GetType().GetProperties(attr))
            {
                if (property.CanRead)
                {
                    dict.Add(property.Name, property.GetValue(data, null));
                }
            }
            return dict;
        }

        public static Claim TryGetClaim(this ClaimsIdentity identity, string cliamType)
        {
            return identity.Claims.FirstOrDefault(i => i.Type == cliamType);
        }

        public static string TryGetClaimValue(this ClaimsIdentity identity, string cliamType)
        {
            return identity.TryGetClaim(cliamType).IfNotNull(i => i.Value);
        }
    }
}